#ifndef GTAXISCONFIG_H
#define GTAXISCONFIG_H

#include "BasicElement/axisconfig.h"

class GTAxisConfig : public AxisConfig
{
    Q_OBJECT

    Q_PROPERTY(int coreNo READ coreNo WRITE setCoreNo NOTIFY coreNoChanged)
    Q_PROPERTY(int index READ index WRITE setIndex NOTIFY indexChanged)
    Q_PROPERTY(double scale READ scale WRITE setScale NOTIFY scaleChanged)
    Q_PROPERTY(double maxVel READ maxVel WRITE setMaxVel NOTIFY maxVelChanged)
    Q_PROPERTY(double maxAcc READ maxAcc WRITE setMaxAcc NOTIFY maxAccChanged)
    Q_PROPERTY(double positiveLimit READ positiveLimit WRITE setPositiveLimit NOTIFY positiveLimitChanged)
    Q_PROPERTY(double negativeLimit READ negativeLimit WRITE setNegativeLimit NOTIFY negativeLimitChanged)
    Q_PROPERTY(double inPosBand READ inPosBand WRITE setInPosBand NOTIFY inPosBandChanged)
    Q_PROPERTY(int inPosHoldTime READ inPosHoldTime WRITE setInPosHoldTime NOTIFY inPosHoldTimeChanged)

    Q_PROPERTY(QString gtHomeMode READ gtHomeMode WRITE setGtHomeMode NOTIFY gtHomeModeChanged)
    Q_PROPERTY(int homeDir READ homeDir WRITE setHomeDir NOTIFY homeDirChanged)
    Q_PROPERTY(int indexDir READ indexDir WRITE setIndexDir NOTIFY indexDirChanged)
    Q_PROPERTY(int edge READ edge WRITE setEdge NOTIFY edgeChanged)
    Q_PROPERTY(double velHigh READ velHigh WRITE setVelHigh NOTIFY velHighChanged)
    Q_PROPERTY(double velLow READ velLow WRITE setVelLow NOTIFY velLowChanged)
    Q_PROPERTY(double escapeStep READ escapeStep WRITE setEscapeStep NOTIFY escapeStepChanged)
    Q_PROPERTY(double gtHomeOffset READ gtHomeOffset WRITE setGtHomeOffset NOTIFY gtHomeOffsetChanged)

public:
    enum GTHomeMode
    {
        HOME_MODE_LIMIT = 10,
        HOME_MODE_LIMIT_HOME = 11,
        HOME_MODE_LIMIT_INDEX = 12,
        HOME_MODE_LIMIT_HOME_INDEX = 13,
        HOME_MODE_HOME = 20,
        HOME_MODE_HOME_INDEX = 22,
        HOME_MODE_INDEX = 30,
    };
    Q_ENUM(GTHomeMode)

    static EnumHelper<GTHomeMode> &GTHomeModeEnumInfo()
    {
        static EnumHelper<GTHomeMode> instance(staticMetaObject, "GTHomeMode");
        return instance;
    }

    Q_INVOKABLE GTAxisConfig(QObject *parent = nullptr) : AxisConfig(parent)
    {
        setOptionalProperty("gtHomeMode", toVariantList(GTHomeModeEnumInfo().names()));
        QVariantList zeroOne;
        zeroOne << 0 << 1;
        setOptionalProperty("homeDir", zeroOne);
        setOptionalProperty("indexDir", zeroOne);
        setOptionalProperty("edge", zeroOne);
        init();
    }

    int coreNo() const
    {
        return m_coreNo;
    }

    int index() const
    {
        return m_index;
    }

    double maxVel() const
    {
        return m_maxVel;
    }

    double maxAcc() const
    {
        return m_maxAcc;
    }

    double inPosBand() const
    {
        return m_inPosBand;
    }

    int inPosHoldTime() const
    {
        return m_inPosHoldTime;
    }

    double positiveLimit() const
    {
        return m_positiveLimit;
    }

    double negativeLimit() const
    {
        return m_negativeLimit;
    }

    QString gtHomeMode() const
    {
        return m_gtHomeMode;
    }

    int homeDir() const
    {
        return m_homeDir;
    }

    int indexDir() const
    {
        return m_indexDir;
    }

    int edge() const
    {
        return m_edge;
    }

    double velHigh() const
    {
        return m_velHigh;
    }

    double velLow() const
    {
        return m_velLow;
    }

    double escapeStep() const
    {
        return m_escapeStep;
    }

    double scale() const
    {
        return m_scale;
    }

    double gtHomeOffset() const
    {
        return m_gtHomeOffset;
    }

public slots:
    void setCoreNo(int coreNo)
    {
        if (m_coreNo == coreNo)
            return;

        m_coreNo = coreNo;
        emit coreNoChanged(m_coreNo);
    }

    void setIndex(int index)
    {
        if (m_index == index)
            return;

        m_index = index;
        emit indexChanged(m_index);
    }

    void setMaxVel(double maxVel)
    {
//        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_maxVel, maxVel))
            return;

        m_maxVel = maxVel;
        emit maxVelChanged(m_maxVel);
    }

    void setMaxAcc(double maxAcc)
    {
//        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_maxAcc, maxAcc))
            return;

        m_maxAcc = maxAcc;
        emit maxAccChanged(m_maxAcc);
    }

    void setInPosBand(double inPosBand)
    {
//        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_inPosBand, inPosBand))
            return;

        m_inPosBand = inPosBand;
        emit inPosBandChanged(m_inPosBand);
    }

    void setInPosHoldTime(int inPosHoldTime)
    {
        if (m_inPosHoldTime == inPosHoldTime)
            return;

        m_inPosHoldTime = inPosHoldTime;
        emit inPosHoldTimeChanged(m_inPosHoldTime);
    }

    void setPositiveLimit(double positiveLimit)
    {
//        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_positiveLimit, positiveLimit))
            return;

        m_positiveLimit = positiveLimit;
        emit positiveLimitChanged(m_positiveLimit);
    }

    void setNegativeLimit(double negativeLimit)
    {
//        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_negativeLimit, negativeLimit))
            return;

        m_negativeLimit = negativeLimit;
        emit negativeLimitChanged(m_negativeLimit);
    }

    void setGtHomeMode(QString gtHomeMode)
    {
        if (m_gtHomeMode == gtHomeMode)
            return;

        m_gtHomeMode = gtHomeMode;
        emit gtHomeModeChanged(m_gtHomeMode);
    }

    void setHomeDir(int homeDir)
    {
        if (m_homeDir == homeDir)
            return;

        m_homeDir = homeDir;
        emit homeDirChanged(m_homeDir);
    }

    void setIndexDir(int indexDir)
    {
        if (m_indexDir == indexDir)
            return;

        m_indexDir = indexDir;
        emit indexDirChanged(m_indexDir);
    }

    void setEdge(int edge)
    {
        if (m_edge == edge)
            return;

        m_edge = edge;
        emit edgeChanged(m_edge);
    }

    void setVelHigh(double velHigh)
    {
//        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_velHigh, velHigh))
            return;

        m_velHigh = velHigh;
        emit velHighChanged(m_velHigh);
    }

    void setVelLow(double velLow)
    {
//        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_velLow, velLow))
            return;

        m_velLow = velLow;
        emit velLowChanged(m_velLow);
    }

    void setEscapeStep(double escapeStep)
    {
//        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_escapeStep, escapeStep))
            return;

        m_escapeStep = escapeStep;
        emit escapeStepChanged(m_escapeStep);
    }

    void setScale(double scale)
    {
//        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_scale, scale))
            return;

        m_scale = scale;
        emit scaleChanged(m_scale);
    }

    void setGtHomeOffset(double gtHomeOffset)
    {
//        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_gtHomeOffset, gtHomeOffset))
            return;

        m_gtHomeOffset = gtHomeOffset;
        emit gtHomeOffsetChanged(m_gtHomeOffset);
    }

signals:
    void coreNoChanged(int coreNo);

    void indexChanged(int index);

    void maxVelChanged(double maxVel);

    void maxAccChanged(double maxAcc);

    void inPosBandChanged(double inPosBand);

    void inPosHoldTimeChanged(int inPosHoldTime);

    void positiveLimitChanged(double positiveLimit);

    void negativeLimitChanged(double negativeLimit);

    void gtHomeModeChanged(QString gtHomeMode);

    void homeDirChanged(int homeDir);

    void indexDirChanged(int indexDir);

    void edgeChanged(int edge);

    void velHighChanged(double velHigh);

    void velLowChanged(double velLow);

    void escapeStepChanged(double escapeStep);

    void scaleChanged(double scale);

    void gtHomeOffsetChanged(double gtHomeOffset);

private:
    int m_coreNo = 1;
    int m_index = 1;
    double m_maxVel = 1;
    double m_maxAcc = 10;
    double m_inPosBand = 0.005;
    int m_inPosHoldTime = 3;
    double m_positiveLimit = 1;
    double m_negativeLimit = -1;
    QString m_gtHomeMode = "HOME_MODE_LIMIT_HOME";
    int m_homeDir = 0;
    int m_indexDir = 1;
    int m_edge = 1;
    double m_velHigh = 1;
    double m_velLow = 0.1;
    double m_escapeStep = 0;
    double m_scale = 1000;
    double m_gtHomeOffset = 0;
};

#endif    // GTAXISCONFIG_H
